package com.yumeng.common.helper;

import com.yumeng.common.data.enums.BaseEnum;
import com.yumeng.common.exception.YumengException;
import org.apache.commons.collections4.MapUtils;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author wxd
 * @date 2022/6/2 15:44
 */
public class BaseEnumHelper {

    private static final Map<String, Map<Integer, BaseEnum>> ENUM_MAP = new LinkedHashMap<>();

    /**
     * 通过枚举类型和code值获取对应的枚举类型
     * @param baseEnumType
     * @param code
     * @param <T>
     * @return
     */
    public static <T extends BaseEnum> T getEnum(Class<? extends BaseEnum> baseEnumType, Integer code) {
        return getEnum(baseEnumType, code, true);
    }

    /**
     * 通过枚举类型和code值获取对应的枚举类型
     * @param baseEnumType
     * @param code
     * @param <T>
     * @return
     */
    public static <T extends BaseEnum> T getEnum(Class<? extends BaseEnum> baseEnumType, Integer code, boolean strict) {
        BaseEnum baseEnum = getBaseEnum(baseEnumType, code, strict);
        return baseEnum != null ? (T)baseEnum : null;
    }

    /**
     * 判断code在枚举中是否存在
     * @param baseEnumType
     * @param code
     * @return
     */
    public static boolean exists(Class<? extends BaseEnum> baseEnumType, Integer code) {
        BaseEnum baseEnum = getBaseEnum(baseEnumType, code, false);
        if (baseEnum == null) {
            return false;
        }
        return true;
    }

    /**
     * 判断code在枚举中是否不存在
     * @param baseEnumType
     * @param code
     * @return
     */
    public static boolean notExists(Class<? extends BaseEnum> baseEnumType, Integer code) {
        return !exists(baseEnumType, code);
    }

    /**
     * 根据code获取描述
     * @param baseEnumType
     * @param code
     * @return
     */
    public static String getDesc(Class<? extends BaseEnum> baseEnumType, Integer code) {
        BaseEnum baseEnum = getBaseEnum(baseEnumType, code, true);
        if (baseEnum == null) {
            return null;
        }
        return baseEnum.getDesc();
    }

    /**
     * 根据code获取BaseEnum
     * @param baseEnumType
     * @param code
     * @return
     */
    public static BaseEnum getBaseEnum(Class<? extends BaseEnum> baseEnumType, Integer code, boolean strict) {
        Map<Integer, BaseEnum> map = getBaseEnumMap(baseEnumType);
        if (code == null) {
            if (strict) {
                throw new YumengException("枚举值不能为null：【%s】", baseEnumType.getName());
            }else{
                return null;
            }
        }
        BaseEnum baseEnum = map.get(code);
        if (strict && baseEnum == null){
            throw new YumengException("枚举值不存在【%s】【%s】", baseEnumType.getName(), code);
        }
        return baseEnum;
    }

    /**
     * 获取所有枚举map
     * @return
     */
    public static Map<String, Map<Integer, BaseEnum>> getBaseEnumMap() {
        return ENUM_MAP;
    }

    /**
     * 通过类型获取枚举map
     * @param baseEnumType
     * @return
     */
    public static Map<Integer, BaseEnum> getBaseEnumMap(Class<? extends BaseEnum> baseEnumType) {
        Map<Integer, BaseEnum> map = ENUM_MAP.get(baseEnumType.getName());
        if (map == null){
            throw new YumengException("枚举类型缺失：%s", baseEnumType.getName());
        }
        return map;
    }

    /**
     * 按类型获取code集合
     * @param baseEnumType
     * @return
     */
    public static Set<Integer> getCodeSet(Class<? extends BaseEnum> baseEnumType) {
        Map<Integer, BaseEnum> map = getBaseEnumMap(baseEnumType);
        return map.keySet();
    }

    /**
     * 按类型获取BaseEnum集合
     * @param baseEnumType
     * @return
     */
    public static Collection<BaseEnum> getBaseEnums(Class<? extends BaseEnum> baseEnumType) {
        Map<Integer, BaseEnum> map = getBaseEnumMap(baseEnumType);
        if (MapUtils.isEmpty(map)) {
            return null;
        }
        return map.values();
    }

}
